#include "../utils/utils.hpp"
#include "omelette.hpp"

using namespace omelette;

bool test_same_futures() {
	bool ok = true;
	Rand r(0);
	State a(r);
	State b(r);
	State c(a);

	a.act(Op::grab());
	b.act(Op::grab());
	c.act(Op::grab());

	if (a != b) {
		testpr("A and b differ");
		ok = false;
	}
	if (a != c) {
		testpr("A and c differ");
		ok = false;
	}
	if (b != c) {
		testpr("B and c differ");
		ok = false;
	}
	
	return ok;
}

bool test_diff_futures() {
	bool ok = true;
	Rand r0(0);
	Rand r1(1);
	State a(r0);
	State b(r1);

	State c = a.future();
	while (c.rng == a.rng)
		c = a.future();

	a.act(Op::grab());
	b.act(Op::grab());
	c.act(Op::grab());

	if (a == b) {
		testpr("A and b are the same");
		ok = false;
	}
	if (a == c) {
		testpr("A and c are the same");
		ok = false;
	}
	if (b == c) {
		testpr("B and c are the same");
		ok = false;
	}
	
	return ok;
}

bool test_mixed_futures() {
	bool ok = true;
	Rand r0(0);
	State a(r0);
	State b(a);

	State c = a.future();
	while (c.rng == a.rng)
		c = a.future();

	a.act(Op::grab());
	b.act(Op::grab());
	c.act(Op::grab());

	if (a != b) {
		testpr("A and b are different");
		ok = false;
	}
	if (a == c) {
		testpr("A and c are the same");
		ok = false;
	}
	if (b == c) {
		testpr("B and c are the same");
		ok = false;
	}
	
	return ok;
}

static const Test tests[] = {
	Test("Same futures test", test_same_futures),
	Test("Different futures test", test_diff_futures),
	Test("Mixed futures test", test_mixed_futures),
};

enum { Ntests = sizeof(tests) / sizeof(tests[0]) };

static const Benchmark benches[] = {
};

enum { Nbenches = sizeof(benches) / sizeof(benches[0]) };

int main(int argc, const char *argv[]) {
	const char *regexp = ".*";
	if (argc == 2)
		regexp = argv[1];

	bool ok = runtests(tests, Ntests, regexp);
	runbenches(benches, Nbenches, regexp);

	return ok ? 0 : 1;
}
